import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { navigate, getPathWithNoRootPath } from 'utils/router';
import { Button, Badge, Tab, Balloon, Menu, Dropdown, Tag, Divider } from '@teamix/ui';
import Pagination from 'components/commonPagination';
import {
  Header,
  Body,
  BodyContent,
  OperationBar,
  Content,
  SearchIcon,
  ButtonIcon,
  YunxiaoList,
} from '@alife/devops-ui';
import { getCachedRepoValue } from 'utils/repoIdCache';
import utils from 'utils';
import debounce from 'lodash.debounce';
import MrSkeleton from 'components/skeleton/orgMr';
import CrListItem from 'components/crListItem';
import ListEmpty from 'atComponents/ListEmpty';
import track, { enterPage, Perf } from 'utils/track';
import CrAdvancedSearch from 'components/crAdvancedSearchDashbord';
import CreateCRModal from 'components/createCRModal/loadable';
import GitRepoTip from 'components/gitRepoTip';
import * as actions from '../actions/index';
import KEYCODE from 'utils/keycode';
import { ENUM } from 'utils/constants';
import docs from 'utils/docs';
import exceed from 'utils/apimap';
import intl from '../../../../../../../locale';
const hasCopy = false;
const hasAll = true;

const mergeEmptyhander = (
  <div>
    <p>通过自动化+人工代码评审，保障代码合入质量</p>
    <a href={docs('mr_intro')} target="_blank " rel="noreferrer">
      如何利用评审实现高质量合并？
    </a>
  </div>
);

const trackPageEnum = {
  created: 'Organization-MRs-My Create',
  reviewed: 'Organization-MRs-My Review',
  all: 'Organization-MRs-All', // 侧导改版后只有它有用了
};

const { ctrlKey, ctrlTxt } = ENUM.getOSKeyMap();

class Root extends Component {
  static propTypes = {
    navKey: PropTypes.string,
    tabKey: PropTypes.string,
    orderKey: PropTypes.string,
    mergeRequests: PropTypes.arrayOf(PropTypes.object),
    currentPage: PropTypes.number,
    totalData: PropTypes.number,

    getMergeRequests: PropTypes.func,
    setNavKey: PropTypes.func,
    setSearch: PropTypes.func,
    setSearchValue: PropTypes.func,
    setTabKey: PropTypes.func,
    setOrderKey: PropTypes.func,
  };

  constructor(props) {
    super(props);
    this.onSearch = debounce(this.onSearch, 500);
    this.cacheKey = getCachedRepoValue('user');
  }

  state = {
    activeKey: 'opened',
    tagsData: {},
    repoDataSource: [],
    pageSize: 10,
  };

  componentDidMount() {
    const navKey = utils.getUrlSearchParam('navKey') || 'all';
    const searchValue = utils.getCachedData(`advanced-search-${this.cacheKey}`);
    this.props.setNavKey(navKey);
    this.props.setSearchValue(searchValue);
    this.props.setResetList();
    this.props.getIpWhite(); // 白名单
    document.addEventListener('keydown', this.handleKeyCodeEvent);
    enterPage(trackPageEnum[navKey], {
      sendPerf: false,
    });
    // this.props.getCloneDownloadSetting();
  }

  handleKeyCodeEvent = (e) => {
    // ctrl + / 进行搜索
    if (e[ctrlKey] && e.keyCode === KEYCODE.SPLIT) {
      document.querySelector('.search-ctrl>button').click();
      document.querySelector('.search-ctrl input').focus();
    }
  };

  componentDidUpdate(prevProps) {
    if (this.props.location.search !== prevProps.location.search) {
      const navKey = utils.getUrlSearchParam('navKey') || 'created';
      const searchValue = utils.getCachedData(`advanced-search-${this.cacheKey}`);
      this.props.setNavKey(navKey);
      this.props.setSearchValue(searchValue);
      this.props.setResetList();
      this.props.updateData({
        search: '',
      });
    }
  }

  componentWillUnmount() {
    document.removeEventListener('keydown', this.handleKeyCodeEvent);
    this.props.resetData();
  }

  // 搜索条件
  onSearch = (search) => {
    const { navKey } = this.props;
    track({
      action: 'search_mr',
      page: trackPageEnum[navKey],
    });

    this.props.setSearch(search);
  };

  // 排序
  onOrderKeySelect = (orderKey) => {
    this.props.setOrderKey(orderKey.toString());
  };

  // tab切换
  onTabKeySelectChange = (tabKey) => {
    this.props.setTabKey(tabKey);
  };

  getTotal = (key) => {
    const { totalData } = this.props;
    return totalData[key];
  };

  onPageChange = (value) => {
    const { pageSize } = this.state;
    this.props.getMergeRequests(value, pageSize);
  };

  onPageSizeChange = (pageSize) => {
    this.setState(
      {
        pageSize,
      },
      () => {
        this.onPageChange(1);
      },
    );
  };

  onCreateCRClick = () => {
    const { navKey } = this.props;
    track({
      action: 'new_mr',
      page: trackPageEnum[navKey],
    });
  };

  crSearchTags = (data) => {
    const { tagsData } = this.state;
    this.setState({
      tagsData: {
        authorData: data.authorData === undefined ? tagsData.authorData : data.authorData,
        assigneeData: data.assigneeData === undefined ? tagsData.assigneeData : data.assigneeData,
        repositoryData:
          data.repositoryData === undefined ? tagsData.repositoryData : data.repositoryData,
      },
    });
  };

  onClose = (item, type) => {
    const { tagsData } = this.state;
    const { repositoryData = [], authorData = [], assigneeData = [] } = tagsData;
    let newRepositoryData;
    let newAuthorData;
    let newAssigneeData;
    switch (type) {
      case 'repositoryData': {
        newRepositoryData = repositoryData.filter((v) => v.value !== item.value);
        break;
      }
      case 'assigneeData': {
        newAssigneeData = assigneeData.filter((v) => v._userId !== item._userId);
        break;
      }
      case 'authorData': {
        newAuthorData = authorData.filter(
          (v) => v._userId !== item._userId || v.tb_user_id !== item.tb_user_id,
        );
        break;
      }
      default:
        break;
    }

    const formDataStr = JSON.stringify({
      authorData: newAuthorData === undefined ? authorData : newAuthorData,
      assigneeData: newAssigneeData === undefined ? assigneeData : newAssigneeData,
      repoData: newRepositoryData === undefined ? repositoryData : newRepositoryData,
    });

    utils.setCachedData(`advanced-search-${this.cacheKey}`, formDataStr);
    const { pathname } = window.location;
    this.setState({
      tagsData: {
        authorData: newAuthorData === undefined ? authorData : newAuthorData,
        assigneeData: newAssigneeData === undefined ? assigneeData : newAssigneeData,
        repositoryData: newRepositoryData === undefined ? repositoryData : newRepositoryData,
      },
    });

    navigate(`${getPathWithNoRootPath(pathname)}?navKey=all&search=${new Date().getTime()}&source=tags`);
  };

  onClearFilter = () => {
    this.setState({
      tagsData: {
        authorData: [],
        assigneeData: [],
        repositoryData: [],
      },
    });

    const { pathname } = window.location;
    utils.setCachedData(`advanced-search-${this.cacheKey}`, undefined);
    navigate(`${getPathWithNoRootPath(pathname)}?navKey=all&search=${new Date().getTime()}source=tags`);
  };

  renderCrSearchTags = () => {
    const { tagsData, activeKey, repoDataSource } = this.state;
    const { repositoryData = [], authorData = [], assigneeData = [] } = tagsData;
    // subscriberData
    const repository = repositoryData.map((item) => (
      <Tag.Closeable
        key={`${item.value}-project`}
        className="cr-search-tags"
        onClose={() => this.onClose(item, 'repositoryData')}
        closeArea="tail"
      >
        {intl.get({
          id: 'code-assets.mergeRequests.containers.root.CodeBase',
          defaultMessage: '代码库：',
        })}
        {
          <Balloon.Tooltip
            popupStyle={{ color: '#f7f7f7', background: '#595959' }}
            align="t"
            trigger={item.name_with_namespace.split(' / ').pop()}
          >
            {item.name_with_namespace}
          </Balloon.Tooltip>
        }
      </Tag.Closeable>
    ));

    const assignee = assigneeData.map((item) => (
      <Tag.Closeable
        key={`${item._userId}-assignee`}
        className="cr-search-tags"
        onClose={() => this.onClose(item, 'assigneeData')}
        closeArea="tail"
      >
        {intl.get({
          id: 'code-assets.mergeRequests.containers.root.Reviewer',
          defaultMessage: '评审人：',
        })}

        {item.name}
      </Tag.Closeable>
    ));

    const author = authorData.map((item) => (
      <Tag.Closeable
        key={`${item._userId}-author`}
        className="cr-search-tags"
        onClose={() => this.onClose(item, 'authorData')}
        closeArea="tail"
      >
        {intl.get({
          id: 'code-assets.mergeRequests.containers.root.Created',
          defaultMessage: '创建人：',
        })}

        {item.name}
      </Tag.Closeable>
    ));

    const hasExtra = repository.length || author.length || assignee.length;
    if (!hasExtra) return null;
    const extra = hasExtra
      ? [
        <CrAdvancedSearch
          {...this.props}
          onProjectList={this.onProjectList}
          onGroupSubProjectList={this.onGroupSubProjectList}
          repoDataSource={repoDataSource}
          hasCopy={hasCopy}
          hasAll={hasAll}
          authControl
          crSearchTags={this.crSearchTags}
          activeKey={activeKey}
          renderHtml={
            <Button type="primary" className="cr-search-tags-btn" text>
              {intl.get({
                  id: 'code-assets.mergeRequests.containers.root.Add',
                  defaultMessage: '添加',
                })}
            </Button>
            }
          addr="btn"
        />,

        <span style={{ margin: '0 2px', color: '#dadde5' }}>|</span>,
        <Button type="primary" className="cr-search-tags-btn" text onClick={this.onClearFilter}>
          {intl.get({
              id: 'code-assets.mergeRequests.containers.root.Empty',
              defaultMessage: '清空',
            })}
        </Button>,
        ]
      : [];
    return (
      <div className="cr-search-tags-outer">
        {[...repository, ...author, ...assignee]}
        <div className="add-and-clear">{extra}</div>
      </div>
    );
  };

  renderPageHeader = () => {
    const { activeKey, repoDataSource } = this.state;
    const { orderKey, navKey } = this.props;
    const extra = (
      <>
        <SearchIcon
          direction="rtl"
          placeholder={intl.get({
            id: 'code-assets.src.utils.locale.SearchReview',
            defaultMessage: '搜索评审',
          })}
          onChange={(value) => {
            this.onSearch(value);
          }}
          defaultValue={this.props.search}
          triggerTooltipProps={{
            children: (
              <div>
                {intl.get({
                  id: 'code-assets.mergeRequests.containers.root.Search',
                  defaultMessage: '搜索',
                })}
                <br />
                {ctrlTxt} + /
              </div>
            ),

            align: 't',
          }}
          className="search-ctrl"
        />

        <CrAdvancedSearch
          {...this.props}
          onProjectList={this.onProjectList}
          onGroupSubProjectList={this.onGroupSubProjectList}
          repoDataSource={repoDataSource}
          hasCopy={hasCopy}
          hasAll={hasAll}
          authControl
          crSearchTags={this.crSearchTags}
          activeKey={activeKey}
          addr="icon"
        />

        <Dropdown
          trigger={<ButtonIcon type="primary" text name="sort-line" />}
          triggerType="click"
          align="tr br"
        >
          <Menu onSelect={this.onOrderKeySelect} selectMode="single" selectedKeys={orderKey}>
            <Menu.Item
              key="updated_at"
              onClick={() => {
                track({
                  action: 'sort_by_update',
                  page: trackPageEnum[navKey],
                });
              }}
            >
              {intl.get({
                id: 'code-assets.src.utils.locale.UpdateTime',
                defaultMessage: '更新时间',
              })}
            </Menu.Item>
            <Menu.Item
              key="created_at"
              onClick={() => {
                track({
                  action: 'sort_by_create',
                  page: trackPageEnum[navKey],
                });
              }}
            >
              {intl.get({
                id: 'code-assets.src.utils.locale.Created',
                defaultMessage: '创建时间',
              })}
            </Menu.Item>
          </Menu>
        </Dropdown>
        <Divider direction="ver" />
        <CreateCRModal
          trigger={
            <Button type="primary" onClick={this.onCreateCRClick}>
              {intl.get({
                id: 'code-assets.mergeRequests.containers.root.New',
                defaultMessage: '新建合并请求',
              })}
            </Button>
          }
          {...this.props}
        />
      </>
    );

    return (
      <Header
        title={intl.get({
          id: 'code-assets.mergeRequests.containers.root.MergeRequest',
          defaultMessage: '合并请求',
        })}
        operation={extra}
      />
    );
  };

  renderEmpty = () => {
    const { search, tabKey } = this.props;
    if (search) {
      return (
        <ListEmpty
          fullPage
          type="org"
          className="cr-list-empty no-btns"
          content=""
          description="抱歉，未找到匹配结果"
          imgType="search"
        />
      );
    } else if (tabKey === 'opened ') {
      return (
        <ListEmpty
          fullPage
          type="org"
          className="cr-list-empty"
          image="none"
          content="暂无待处理的合并请求，放松一下吧"
          description={mergeEmptyhander}
        />
      );
    } else {
      return (
        <ListEmpty
          fullPage
          type="org"
          className="cr-list-empty"
          image="none"
          content={intl.get({
            id: 'code-assets.mergeRequests.containers.root.NoMergeRequestRecordsAre',
            defaultMessage: '暂无合并请求记录',
          })}
          description={mergeEmptyhander}
        />
      );
    }
  };

  onChangeTab = (key) => {
    this.setState({
      activeKey: key,
    });
  };

  onProjectList = (search, size) => {
    exceed
      .fetch({
        api: 'projects.authorizedList',
        data: {
          contains_sub_projects: true,
          search,
          size,
          order_by: 'last_activity_at',
        },
      })
      .then((list) => {
        list.shift();
        const repoDataSource = [
          {
            label: intl.get({
              id: 'code-assets.mergeRequests.containers.root.LastUpdated',
              defaultMessage: '最近更新',
            }),

            children: [],
          },
        ];

        if (list && list.length) {
          repoDataSource[0].children.push(
            ...list.slice(0, size).map((project) => ({
              label: project.name,
              value: project.id,
              name_with_namespace: utils.getGroupPath(project.name_with_namespace),
            })),
          );
        }
        this.setState({
          repoDataSource,
        });
      });
  };

  onGroupSubProjectList = (search, size = 5) => {
    const { pathResource } = window.FORCE;
    exceed
      .fetch({
        api: 'groups.all.subprojects',
        data: {
          namespace_id: pathResource.id,
          search,
          size,
          order_by: 'last_activity_at',
        },
      })
      .then((list) => {
        list.shift();
        const repoDataSource = [
          {
            label: intl.get({
              id: 'code-assets.mergeRequests.containers.root.LastUpdated',
              defaultMessage: '最近更新',
            }),

            children: [],
          },
        ];

        if (list && list.length) {
          repoDataSource[0].children.push(
            ...list.slice(0, size).map((project) => ({
              label: project.name,
              value: project.id,
              name_with_namespace: utils.getGroupPath(project.name_with_namespace),
            })),
          );
        }
        this.setState({
          repoDataSource,
        });
      });
  };

  render() {
    const { mergeRequests, isLoading, currentPage, totalData, tabKey, navKey } = this.props;
    return (
      <React.Fragment>
        {this.renderPageHeader()}
        <Body className="merge-container-root">
          <BodyContent>
            <OperationBar>
              {this.renderCrSearchTags()}

              <Tab
                onChange={this.onChangeTab}
                activeKey={this.state.activeKey}
                className="cr-search-tabs"
                animation={false}
              >
                <Tab.Item
                  title={
                    <span className="title-span-badge">
                      <span>
                        {intl.get({
                          id: 'code-assets.mergeRequests.containers.root.Enabled',
                          defaultMessage: '已开启',
                        })}
                      </span>
                      <Badge count={this.getTotal('opened')} showZero />
                    </span>
                  }
                  key="opened"
                />
                <Tab.Item
                  title={
                    <span className="title-span-badge">
                      <span>
                        {intl.get({
                          id: 'code-assets.mergeRequests.containers.root.Merged',
                          defaultMessage: '已合并',
                        })}
                      </span>
                      <Badge count={this.getTotal('merged')} showZero />
                    </span>
                  }
                  key="merged"
                />

                <Tab.Item
                  title={
                    <span className="title-span-badge">
                      <span>
                        {intl.get({
                          id: 'code-assets.mergeRequests.containers.root.Disabled',
                          defaultMessage: '已关闭',
                        })}
                      </span>
                      <Badge count={this.getTotal('closed')} showZero />
                    </span>
                  }
                  key="closed"
                />

                <Tab.Item
                  title={
                    <span className="title-span-badge">
                      <span>
                        {intl.get({
                          id: 'code-assets.mergeRequests.containers.root.All',
                          defaultMessage: '全部',
                        })}
                      </span>
                      <Badge count={this.getTotal('all')} showZero />
                    </span>
                  }
                  key="all"
                />
              </Tab>
            </OperationBar>
            <Content>
              {!isLoading ? (
                <>
                  {mergeRequests.length === 0 ? (
                    this.renderEmpty()
                  ) : (
                    <YunxiaoList
                      className="cr-list"
                      dataSource={mergeRequests}
                      renderItem={(item, i) => (
                        <CrListItem
                          item={YunxiaoList.Item}
                          key={i}
                          projectCloneDownload={item.projectCloneDownload}
                          ipSetting={this.props.ipSetting}
                          codeReview={item}
                          pageType="Home-Page-MR"
                        />
                      )}
                    />
                  )}

                  <Perf page={trackPageEnum[navKey]} />
                </>
              ) : (
                <MrSkeleton />
              )}
            </Content>
            <Pagination
              current={currentPage}
              total={totalData[tabKey]}
              onChange={this.onPageChange}
              pageSize={this.state.pageSize}
              onPageSizeChange={this.onPageSizeChange}
              leftWidth={420}
              footerProps={{
                left: <GitRepoTip />,
              }}
            />
          </BodyContent>
        </Body>
      </React.Fragment>
    );
  }
}

export default connect(
  (state) => state.organization.mergeRequests,
  (dispatch) => bindActionCreators(actions, dispatch),
)(Root);
